import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from 'axios';
import qs from 'qs';
import { useUserStoreHook } from '@/store/modules/user.store';
import { ResultEnum } from '@/enums/api/result.enum';
import { getAccessToken } from '@/utils/auth';
import router from '@/router';
import { Session } from '@/utils/storage';
import { encryption, adaptationUrl } from '@/utils/crypto';

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
  headers: { 'Content-Type': 'application/json;charset=utf-8' },
  paramsSerializer: {
    serialize: (params: any) => qs.stringify(params, { arrayFormat: 'repeat' }),
  },
});
// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 统一增加Authorization请求头, skipToken 跳过增加token
    const token = Session.getToken();
    if (!config.headers?.skipToken && token) {
      config.headers![CommonHeaderEnum.AUTHORIZATION] = `Bearer ${token}`;
    }
    // 请求报文加密
    if (config.headers![CommonHeaderEnum.ENC_FLAG]) {
      const enc = encryption(JSON.stringify(config.data), import.meta.env.VITE_PWD_ENC_KEY);
      config.data = {
        encryption: enc,
      };
    }
    // const accessToken = getAccessToken();
    // // 如果 Authorization 设置为 no-auth，则不携带 Token
    // if (config.headers.Authorization !== "no-auth" && accessToken) {
    //   config.headers.Authorization = `Bearer ${accessToken}`;
    // } else {
    //   delete config.headers.Authorization;
    // }
    // 自动适配单体和微服务架构不同的URL
    config.url = adaptationUrl(config.url);
    return config;
  },
  (error) => Promise.reject(error)
);
// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 如果响应是二进制流，则直接返回，用于下载文件、Excel 导出等
    if (response.config.responseType === 'blob') {
      return response;
    }
    // console.log('res-', response);

    if (response.config.url?.includes('oauth2/token')) {
      return response.data;
    } else {
      const { code, data, msg } = response.data; // {code: 0, data: {}, msg: null, success: true}
      if (code === ResultEnum.SUCCESS) {
        return data;
      }
      ElMessage.error(msg || '系统出错');
      return Promise.reject(new Error(msg || 'Error'));
    }
  },
  async (error) => {
    console.error('request error', error); // for debug
    const { config, response } = error;
    if (response) {
      const { code, msg } = response.data; // response.status === 500
      if (code === ResultEnum.ACCESS_TOKEN_INVALID) {
        // Access Token 过期，尝试刷新
        await handleSessionExpired();
        return Promise.reject(new Error(msg || 'Error'));
      } else if (code === ResultEnum.REFRESH_TOKEN_INVALID) {
        // Token 过期，刷新 Token
        return handleTokenRefresh(config);
      } else {
        ElMessage.error(msg || '系统出错');
      }
    }
    return Promise.reject(error.message);
  }
);
// 常用header
export enum CommonHeaderEnum {
  'TENANT_ID' = 'TENANT-ID',
  'ENC_FLAG' = 'Enc-Flag',
  'AUTHORIZATION' = 'Authorization',
}

export default service;

// 是否正在刷新标识，避免重复刷新
let isRefreshing = false;
// 因 Token 过期导致的请求等待队列
const waitingQueue: Array<() => void> = [];
// 刷新 Token 处理
async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
  return new Promise((resolve) => {
    // 封装需要重试的请求
    const retryRequest = () => {
      config.headers.Authorization = `Bearer ${getAccessToken()}`;
      resolve(service(config));
    };
    waitingQueue.push(retryRequest);
    if (!isRefreshing) {
      isRefreshing = true;
      useUserStoreHook()
        .refreshToken()
        .then(() => {
          // 依次重试队列中所有请求, 重试后清空队列
          waitingQueue.forEach((callback) => callback());
          waitingQueue.length = 0;
        })
        .catch(async (error) => {
          console.error('handleTokenRefresh error', error);
          // 刷新 Token 失败，跳转登录页
          await handleSessionExpired();
        })
        .finally(() => {
          isRefreshing = false;
        });
    }
  });
}
// 处理会话过期
async function handleSessionExpired() {
  ElNotification({
    title: '提示',
    message: '您的会话已过期，请重新登录',
    type: 'info',
  });
  await useUserStoreHook().clearSessionAndCache();
  router.push('/login');
}

const validateNull = (val: any) => {
  if (typeof val === 'boolean') {
    return false;
  }
  if (typeof val === 'number') {
    return false;
  }
  if (val instanceof Array) {
    if (val.length === 0) return true;
  } else if (val instanceof Object) {
    if (JSON.stringify(val) === '{}') return true;
  } else {
    if (val === 'null' || val == null || val === 'undefined' || val === undefined || val === '')
      return true;
    return false;
  }
  return false;
};
